package com.apobates.jforum2.troll.nest.controller;

import com.apobates.jforum2.threads.stub.vo.ThreadsVo;
import com.apobates.jforum2.troll.accounts.stub.vo.MemberVo;
import com.apobates.jforum2.troll.nest.service.MemberClient;
import com.apobates.jforum2.troll.nest.service.PostsClient;
import com.apobates.jforum2.troll.nest.service.TopicClient;
import com.apobates.jforum2.troll.nest.vo.ReplyCollectMemberVo;
import com.apobates.jforum2.troll.nest.vo.ReplyCollectThreadsVo;
import com.apobates.jforum2.troll.replies.stub.vo.ReplyMoodVo;
import com.apobates.jforum2.troll.replies.stub.vo.ReplyVo;
import com.apobates.jforum2.troll.utils.core.Commons;
import com.apobates.jforum2.troll.utils.core.EntityPageResult;
import com.apobates.jforum2.troll.utils.core.ResponseResult;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

/**
 * 回复Api服务API控制器
 * 注意: 需要带有服务响应的状态码使用ResponseEntity, 对于返回值对象的请求在失败时返回404,对于String响应的操作返回401
 * @author xiaofanku
 * @since 20201116
 */
@RestController
@RequestMapping("/api/reply")
public class PostsClientController{
    @Autowired
    private PostsClient postsClient;
    @Autowired
    private TopicClient topicClient;
    @Autowired
    private MemberClient memberClient;
    private final static Logger logger = LoggerFactory.getLogger(PostsClientController.class);

    //4:查看指定回复
    @GetMapping("/{id}")
    public ReplyVo get(@PathVariable("id")long postsId){
        ResponseEntity<ReplyVo> rs = postsClient.get(postsId);
        return Optional.ofNullable(rs.getBody()).orElse(new ReplyVo());
    }
    
    //5:查看指定回复,级联加载话题
    @GetMapping("/{id}/fold/{topic}")
    public ResponseEntity<ReplyCollectThreadsVo> getCascade(@PathVariable("id")long postsId, @PathVariable("topic")long topicId){
        CompletableFuture<Optional<ReplyVo>> rv = CompletableFuture.supplyAsync(()->postsClient.get(postsId)).thenApply(rvObj->Optional.ofNullable(rvObj.getBody())).completeOnTimeout(Optional.empty(), 1, TimeUnit.SECONDS);
        CompletableFuture<Optional<ThreadsVo>> tv = CompletableFuture.supplyAsync(()->topicClient.get(topicId)).thenApply(tvObj->Optional.ofNullable(tvObj.getBody())).completeOnTimeout(Optional.empty(), 1, TimeUnit.SECONDS);
        //
        Optional<ReplyCollectThreadsVo> rs = rv.thenCombineAsync(tv, (rvOpt, tvOpt)->{
            return rvOpt.map(rins->{
                ReplyCollectThreadsVo tmp = new ReplyCollectThreadsVo();
                tmp.setReplyVo(rins);
                tmp.setThreadsVo(tvOpt.orElse(new ThreadsVo()));
                return tmp;
            });
        }).completeOnTimeout(Optional.empty(), 1, TimeUnit.SECONDS).join();
        //
        ResponseResult<ReplyCollectThreadsVo> rr = ResponseResult.Helper.ofOptional(rs);
        return ResponseEntity.status(rr.getCode()).contentType(MediaType.APPLICATION_JSON).body(rr.getEntity());
    }
    
    //6:统计指定回复者在话题中的回复次数, 1楼不在统计之列.忽略状态值
    @GetMapping("/replies/{topic}/{member}")
    public long countRepliesSize(@PathVariable("topic") long topicId, @PathVariable("member") long memberId){
        return postsClient.countRepliesSize(topicId, memberId);
    }
    
    //7:查看指定话题最近的回复,忽略状态值;以entryDateTime倒序 服务于策略检查
    @GetMapping("/recent/{topic}")
    public List<ReplyVo> getRecentForTopicIgnoreStatus(@PathVariable("topic") long topicId, @RequestParam("size") int minInterruptSize){
        return postsClient.getRecentForTopicIgnoreStatus(topicId, minInterruptSize);
    }
    
    //8:移除回复
    @PutMapping(value="/{id}/remove", consumes="application/x-www-form-urlencoded")
    public boolean delReply(@PathVariable("id") long postsId,
              @RequestParam("member") long memberId,
              @RequestParam("nickname") String memberNickname,
              @RequestParam("token") String token,
              @RequestParam("ip") String ipAddr){
        return postsClient.delReply(postsId, memberId, memberNickname, token, ipAddr);
    }
    
    //9:创建回复
    @PostMapping(value="/create", consumes="application/x-www-form-urlencoded")
    public ResponseEntity<ReplyVo> createReply(
            @RequestParam("volumes") int volumesId,
            @RequestParam("board") long boardId,
            @RequestParam("threads") long topicId,
            @RequestParam("quote") long quotePostsId,
            @RequestParam("content") String content,
            @RequestParam("scale") String scale,
            @RequestParam("member") long memberId,
            @RequestParam("nickname") String memberNickname,
            @RequestParam("token") String token,
            @RequestParam("ip") String ipAddr){
        try {
            return postsClient.createReply(volumesId, boardId, topicId, quotePostsId, content, scale, memberId, memberNickname, token, ipAddr);
        }catch (Exception e){
            logger.error("[nest-reply-topic]ResponseEntity exception:"+e.getMessage());
        }
        return ResponseEntity.notFound().build();
    }
    
    //10:查看指定的回复, 并对内容进行解码(编辑内容)
    @GetMapping("/{id}/content")
    public ReplyVo getPostsContentForEdit(@PathVariable("id") long postsId){
        ResponseEntity<ReplyVo> rs = postsClient.getPostsContentForEdit(postsId);
        return Optional.ofNullable(rs.getBody()).orElse(new ReplyVo());
    }
    
    //11:查看话题最近的回复,不包括楼主的回复,并对回复内容进行解码(RSS)
    @GetMapping("/rss/{topic}")
    public List<ReplyVo> getRecentForRSS(@PathVariable("topic") long topicId, @RequestParam("size") int showSize){
        return postsClient.getRecentForRSS(topicId, showSize);
    }
    
    //12:查看话题中指定会员的所有回复,不包括楼主的话题内容并对回复内容进行图片解码
    @GetMapping("/threads/{topic}/{filterMember}/{scale}/{page}/{number}")
    public EntityPageResult<ReplyCollectMemberVo> getAllReplyFilterAuthor(
            @PathVariable("topic") long topicId,
            @PathVariable("filterMember") long filterMemberId,
            @PathVariable("scale") String imageScale,
            @PathVariable("page") int page,
            @PathVariable("number") int pageSize,
            @RequestParam(value="sort", required=false, defaultValue="0")int sortCategory){
        EntityPageResult<ReplyVo> rs = postsClient.getRepliesOrFilterAuthor(topicId,filterMemberId,imageScale,page,pageSize,sortCategory);
        return EntityPageResult.of(rs.getTotal(), rs.getPage(), rs.getSize(), supplyMemberCollection(rs.getResult()));
    }
    
    //补充会员对象
    private Stream<ReplyCollectMemberVo> supplyMemberCollection(List<ReplyVo> rs){
        List<Long> memberIdList = rs.stream().map(ReplyVo::getMember).collect(Collectors.toList());
        final Map<Long, MemberVo> memberVoMap = memberClient.getMulti(Commons.longToString(memberIdList)).stream().collect(Collectors.toMap(MemberVo::getId, Function.identity()));
        //
        final BiFunction<ReplyVo,MemberVo,ReplyCollectMemberVo> mapper = (rv,mv)->{
            ReplyCollectMemberVo tmp = new ReplyCollectMemberVo();
            tmp.setReplyVo(rv);
            tmp.setMemberVo(mv);
            return tmp;
        };
        return rs.stream().map(rvIns->{
            MemberVo tmp = memberVoMap.getOrDefault(rvIns.getMember(), MemberVo.empty());
            return mapper.apply(rvIns, tmp);
        });
    }
    
    //13:举报回复
    @PostMapping(value="/{id}/report", consumes="application/x-www-form-urlencoded")
    public ResponseEntity<ThreadsVo> report(@PathVariable("id") long postsId,
                  @RequestParam("threads") long topicId,
                  @RequestParam("content") String reportReason,
                  @RequestParam("type") int reportType,
                  @RequestParam("member") long memberId,
                  @RequestParam("nickname") String memberNickname,
                  @RequestParam("token") String token,
                  @RequestParam("ip") String ipAddr){
        try {
            ReplyVo rv = postsClient.get(postsId).getBody();
            if (null == rv) {
                return ResponseEntity.badRequest().build();
            }
            return topicClient.report(topicId, reportReason, reportType, rv.getFloor(), rv.getNickname(), rv.getLink(), rv.getContent(), memberId, memberNickname, token, ipAddr);
        }catch (Exception e){
            logger.error("[nest-reply-report]ResponseEntity exception:"+e.getMessage());
        }
        return ResponseEntity.notFound().build();
    }
    
    //14:编辑回复
    @PutMapping(value="/{id}/modify", consumes="application/x-www-form-urlencoded")
    public ResponseEntity<ReplyVo> modifyReply(@PathVariable("id") long postsId,
                     @RequestParam("content") String content,
                     @RequestParam("member") long memberId,
                     @RequestParam("nickname") String memberNickname,
                     @RequestParam("token") String token,
                     @RequestParam("ip") String ipAddr){
        try {
            return postsClient.modifyReply(postsId, content, memberId, memberNickname, token, ipAddr);
        }catch (Exception e){
            logger.error("[nest-reply-modify]ResponseEntity exception:"+e.getMessage());
        }
        return ResponseEntity.notFound().build();
    }
    
    //15:创建喜好记录.若会员已对回复的喜好记录存在方法会删除并返回成功
    //-1表示删除喜好,大于0表示喜好增加成功,0喜好增加失败
    //200 表示操作成功(DEL表示删除,ADD表示增加), 417 表示操作失败
    @PostMapping(value="/{id}/mood", consumes="application/x-www-form-urlencoded")
    public ResponseEntity<String> toggleMoodRecord(@PathVariable("id") long postsId,
                        @RequestParam("threads")long topicId,
                        @RequestParam("mood") int moodStatus,
                        @RequestParam("member") long memberId,
                        @RequestParam("nickname") String memberNickname,
                        @RequestParam("token") String token,
                        @RequestParam("ip") String ipAddr){
        try {
            return postsClient.toggleMoodRecord(postsId, topicId, moodStatus, memberId, memberNickname, token, ipAddr);
        }catch (Exception e){
            logger.error("[nest-reply-mood]ResponseEntity exception:"+e.getMessage());
        }
        return ResponseEntity.notFound().build();
    }
    
    //16:查看指定回复的喜好记录
    @GetMapping("/threads/{topic}/{id}/mood")
    public ReplyMoodVo getMoodRecordByPosts(@PathVariable("id") long postsId, @PathVariable("topic") long topicId){
        ResponseEntity<ReplyMoodVo> rs = postsClient.getMoodRecordByPosts(postsId, topicId);
        return Optional.ofNullable(rs.getBody()).orElse(new ReplyMoodVo());
    }
    
    //17:查看指定的回复喜好汇总记录
    @PostMapping(value="/mood/query", consumes="application/x-www-form-urlencoded")
    public List<ReplyMoodVo> getByPosts(@RequestParam("threads")long topicId, @RequestParam("records") String postsIdString){
        return postsClient.getByPosts(topicId, postsIdString);
    }
}